package map.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.baidu.mapapi.search.core.SearchResult
import com.baidu.mapapi.search.poi.PoiDetailResult
import com.baidu.mapapi.search.poi.PoiDetailSearchResult
import com.baidu.mapapi.search.poi.PoiIndoorResult
import com.baidu.mapapi.search.poi.PoiResult
import com.baidu.mapapi.utils.DistanceUtil
import com.google.gson.reflect.TypeToken
import com.zjw.zy.ext.launchInIo
import com.zjw.zy.ext.launchInMain
import com.zjw.zy.ext.logD
import com.zjw.zy.ext.longToast
import com.zjw.zy.utils.GsonUtils
import com.zjw.zy.utils.SharePrefUtils
import map.bean.SuggestInfoWrap
import map.default.DefaultGetPoiSearchResultListener
import map.ext.locationManager
import map.ext.map
import map.ext.mapManager
import map.ext.searchManager
import java.util.*

/**
 * @author     ：zhong.jw
 * @date       ：Created in 2022/10/24 11:31
 * @description：
 */
class SearchViewModel : MapBaseViewModel() {

    companion object {
        private const val TAG = "SearchViewModel"
        private const val MAX_SUGGEST_HISTORY = 10
    }

    private val searchResult = MutableLiveData<PoiResult?>()
    fun getSearchResult(): LiveData<PoiResult?> = searchResult

    private val suggestResult = MutableLiveData<List<SuggestInfoWrap>>(getSuggestRecord(true))
    fun getSuggestResult(): LiveData<List<SuggestInfoWrap>> = suggestResult

    //深度搜索poi
    private val mPoiDetail: MutableLiveData<PoiDetailResult?> = MutableLiveData()
    fun getPoiDetails(): LiveData<PoiDetailResult?> = mPoiDetail


    fun nearSearch(keyWord: String) {
        launchInIo {
            searchManager().poiNearSearch(
                locationManager().locationLatLng(),
                keyWord,
                radius = 5000,
                call = object : DefaultGetPoiSearchResultListener {
                    override fun onGetPoiResult(p0: PoiResult?) {
                        if (SearchResult.ERRORNO.NO_ERROR == p0?.error) {
                            launchInMain {
                                map().let {
                                    it.clear()
                                    mapManager().poiOverLay().apply {
                                        //设置poi数据
                                        this.setData(p0)
                                        //添加到地图
                                        this.addToMap()
                                        //设置合适比例尺
                                        this.zoomToSpan()
                                    }
                                }
                            }
                            searchResult.postValue(p0)
                        } else {
                            "poi search failed -> $p0".logD(TAG)
                            "搜索失败".longToast()
                        }
                    }

                    override fun onGetPoiDetailResult(p0: PoiDetailResult?) {
                    }

                    override fun onGetPoiDetailResult(p0: PoiDetailSearchResult?) {
                    }

                    override fun onGetPoiIndoorResult(p0: PoiIndoorResult?) {
                    }
                }
            )
        }
    }

    fun poiSearch(uid: String) {
        searchManager().poiDetailSearch(uid, object : DefaultGetPoiSearchResultListener {
            override fun onGetPoiDetailResult(p0: PoiDetailSearchResult?) {
                //mPoiDetail.postValue(p0)
            }

            override fun onGetPoiDetailResult(p0: PoiDetailResult?) {
                mPoiDetail.postValue(p0)
            }
        })
    }

    fun suggestSearch(keyword: String) {
        launchInIo {
            searchManager().suggestSearch(keyword, call = {
                val myLocation = locationManager().locationLatLng()
                if (it.error == SearchResult.ERRORNO.NO_ERROR) {
                    suggestResult.postValue(it.allSuggestions.map { suggestionInfo ->
                        SuggestInfoWrap(
                            suggestionInfo,
                            DistanceUtil.getDistance(myLocation, suggestionInfo.pt)
                        )
                    })
                } else {
                    suggestResult.postValue(getSuggestRecord(true))
                }
            })
        }
    }


    fun addSuggestRecord(data: SuggestInfoWrap) {
        launchInIo {
            val history = getSuggestRecord()
            if (history.contains(data)) {
                history.remove(data)
                history.add(0, data)
                return@launchInIo
            }
            history.add(0, data)
            if (history.size > MAX_SUGGEST_HISTORY) {
                history.removeLast()
            }
            SharePrefUtils.putString(
                SuggestSearchViewModel.SUGGEST_HISTORY_KEY,
                GsonUtils.toJson(history)
            )
        }
    }

    private fun getSuggestRecord(updateDistance: Boolean = false): ArrayList<SuggestInfoWrap> {
        val json = SharePrefUtils.getString(SuggestSearchViewModel.SUGGEST_HISTORY_KEY, "")
        val history = if (json.isEmpty()) {
            ArrayList<SuggestInfoWrap>()
        } else {
            val type = object : TypeToken<ArrayList<SuggestInfoWrap>>() {}.type
            GsonUtils.fromJson(json, type)
        }

        if (updateDistance) {
            val myLocation = locationManager().locationLatLng()
            history.forEach { record ->
                record.distance =
                    DistanceUtil.getDistance(myLocation, record.suggestionInfo.pt)
            }
        }

        return history
    }

}